/*******************************************************************************
  * 文件：Buffer.c
  * 作者：zyz
  * 版本：v2.0.1
  * 日期：2020-03-24
  * 说明：缓冲区
*******************************************************************************/

/* 头文件 *********************************************************************/
#include "Buffer.h"

/* 宏定义 *********************************************************************/
/* 类型定义 *******************************************************************/
/* 变量定义 *******************************************************************/
/* 函数声明 *******************************************************************/
// 读取数据
static U16 Buffer_Read(BufferHandle_tps psBuffer, U8 *pu8Data, U16 u16DataLen, Bool bRemove);

/* 函数定义 *******************************************************************/

/*******************************************************************************
  * 函数名：Buffer_Init
  * 功  能：初始化
  * 参  数：BufferHandle_tps psBuffer  - 缓冲区句柄
  *         U8 *pu8Buffer              - 缓冲区
  *         U16 u16BufferSize          - 缓冲区大小
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void Buffer_Init(BufferHandle_tps psBuffer, U8 *pu8Buffer, U16 u16BufferSize)
{
    // 初始化读写索引和数据个数
    psBuffer->u16WriteIndex = 0;
    psBuffer->u16ReadIndex  = 0;
    psBuffer->u16DataNum    = 0;

    // 初始化数据缓冲区和大小
    psBuffer->pu8Buffer     = pu8Buffer;
    psBuffer->u16BufferSize = u16BufferSize;
}

/*******************************************************************************
  * 函数名：Buffer_Write
  * 功  能：向缓冲区写入数据
  * 参  数：BufferHandle_tps psBuffer  - 缓冲区句柄
  *         U8 *pu8Data                - 数据
  *         U16 u16DataLen             - 数据长度
  * 返回值：写入个数
  * 说  明：无
*******************************************************************************/
U16 Buffer_Write(BufferHandle_tps psBuffer, U8 *pu8Data, U16 u16DataLen)
{
    U16 u16WriteLen;

    // 写索引小于读索引
    if(psBuffer->u16WriteIndex < psBuffer->u16ReadIndex)
    {
        // 计算缓冲区空闲空间
        U16 u16BufferFreeSpace = psBuffer->u16ReadIndex - psBuffer->u16WriteIndex;

        // 缓冲区空闲空间可以容纳全部数据
        if(u16BufferFreeSpace >= u16DataLen)
        {
            // 将数据全部写入缓冲区
            memcpy(&(psBuffer->pu8Buffer[psBuffer->u16WriteIndex]), pu8Data, u16DataLen);
            // 记录写入长度，更新写索引
            u16WriteLen = u16DataLen;
            psBuffer->u16WriteIndex += u16DataLen;
        }
        // 缓冲区空闲空间不能容纳全部数据
        else
        {
            // 将缓冲区空间写满
            memcpy(&(psBuffer->pu8Buffer[psBuffer->u16WriteIndex]), pu8Data, u16BufferFreeSpace);
            // 记录写入长度，更新写索引
            u16WriteLen = u16BufferFreeSpace;
            psBuffer->u16WriteIndex = psBuffer->u16ReadIndex;
        }
    }
    // 写索引小于读索引，或者缓冲区空（此时写索引等于读索引）
    else if((psBuffer->u16WriteIndex > psBuffer->u16ReadIndex) ||
            (psBuffer->u16DataNum == 0))
    {
        // 计算缓冲区头部和尾部空闲空间
        U16 u16BufferHeadFreeSpace = psBuffer->u16ReadIndex;
        U16 u16BufferTailFreeSpace = psBuffer->u16BufferSize - psBuffer->u16WriteIndex;

        // 缓冲区尾部空闲空间可以容纳全部数据
        if(u16BufferTailFreeSpace >= u16DataLen)
        {
            // 将数据全部写入缓冲区
            memcpy(&(psBuffer->pu8Buffer[psBuffer->u16WriteIndex]), pu8Data, u16DataLen);
            // 记录写入长度，更新写索引
            u16WriteLen = u16DataLen;
            psBuffer->u16WriteIndex += u16DataLen;
            // 写索引溢出缓冲区大小
            if(psBuffer->u16WriteIndex >= psBuffer->u16BufferSize)
            {
                // 写索引指向缓冲区头部
                psBuffer->u16WriteIndex = 0;
            }
        }
        // 缓冲区尾部空闲空间不能容纳全部数据
        else
        {
            // 计算剩余数据大小和指针
            U16 u16RemainDataLen = u16DataLen - u16BufferTailFreeSpace;
            U8 *pu8RemainData = (U8 *)(pu8Data + u16BufferTailFreeSpace);

            // 先把缓冲区尾部空闲空间写满
            memcpy(&(psBuffer->pu8Buffer[psBuffer->u16WriteIndex]), pu8Data, u16BufferTailFreeSpace);

            // 缓冲区头部空闲空间可以容纳剩下的数据
            if(u16BufferHeadFreeSpace >= u16RemainDataLen)
            {
                // 将剩余数据写入缓冲区
                memcpy(&(psBuffer->pu8Buffer[0]), pu8RemainData, u16RemainDataLen);
                // 记录写入长度，更新写索引
                u16WriteLen = u16DataLen;
                psBuffer->u16WriteIndex = u16RemainDataLen;
            }
            // 缓冲区头部空闲空间不能容纳剩下的数据
            else
            {
                // 将剩余数据写满缓冲区头部空闲空间
                memcpy(&(psBuffer->pu8Buffer[0]), pu8RemainData, u16BufferHeadFreeSpace);
                // 记录写入长度，更新写索引
                u16WriteLen = u16BufferTailFreeSpace + u16BufferHeadFreeSpace;
                psBuffer->u16WriteIndex = psBuffer->u16ReadIndex;
            }
        }
    }
    // 缓冲区满了
    else
    {
        // 清零写入长度
        u16WriteLen = 0;
    }

    // 更新缓冲区数据个数
    psBuffer->u16DataNum += u16WriteLen;

    // 返回写入个数
    return u16WriteLen;
}

/*******************************************************************************
  * 函数名：Buffer_Read
  * 功  能：从缓冲区读取数据
  * 参  数：BufferHandle_tps psBuffer  - 缓冲区句柄
  *         U8 *pu8Data                - 数据
  *         U16 u16DataLen             - 数据长度
  *         Bool bRemove               - 移除数据
  * 返回值：读取个数
  * 说  明：无
*******************************************************************************/
static U16 Buffer_Read(BufferHandle_tps psBuffer, U8 *pu8Data, U16 u16DataLen, Bool bRemove)
{
    U16 u16ReadLen;

    // 读索引小于写索引
    if(psBuffer->u16ReadIndex < psBuffer->u16WriteIndex)
    {
        // 计算缓冲区数据个数
        U16 u16BufferDataNum = psBuffer->u16DataNum;

        // 缓冲区数据个数大于或等于读取数据个数
        if(u16BufferDataNum >= u16DataLen)
        {
            // 从缓冲区读取指定长度数据
            memcpy(pu8Data, &(psBuffer->pu8Buffer[psBuffer->u16ReadIndex]), u16DataLen);
            // 记录读取长度，更新读索引
            u16ReadLen = u16DataLen;
            if(bRemove)
            {
                psBuffer->u16ReadIndex += u16DataLen;
            }
        }
        // 缓冲区数据个数小于读取数据个数
        else
        {
            // 从缓冲区读取所有数据
            memcpy(pu8Data, &(psBuffer->pu8Buffer[psBuffer->u16ReadIndex]), u16BufferDataNum);
            // 记录读取长度，更新读索引
            u16ReadLen = u16BufferDataNum;
            if(bRemove)
            {
                psBuffer->u16ReadIndex = psBuffer->u16WriteIndex;
            }
        }
    }
    // 读索引大于写索引，或者缓冲区满（此时读索引等于写索引）
    else if((psBuffer->u16ReadIndex > psBuffer->u16WriteIndex) ||
            (psBuffer->u16DataNum == psBuffer->u16BufferSize))
    {
        // 计算缓冲区头部和尾部数据个数
        U16 u16BufferHeadDataNum = psBuffer->u16WriteIndex;
        U16 u16BufferTailDataNum = psBuffer->u16BufferSize - psBuffer->u16ReadIndex;

        // 缓冲区尾部数据个数大于或者等于读取数据个数
        if(u16BufferTailDataNum >= u16DataLen)
        {
            // 从缓冲区读取指定长度数据
            memcpy(pu8Data, &(psBuffer->pu8Buffer[psBuffer->u16ReadIndex]), u16DataLen);
            // 记录读取长度，更新读索引
            u16ReadLen = u16DataLen;
            if(bRemove)
            {
                psBuffer->u16ReadIndex += u16DataLen;
                // 读索引溢出缓冲区大小
                if(psBuffer->u16ReadIndex >= psBuffer->u16BufferSize)
                {
                    // 读索引指向缓冲区头部
                    psBuffer->u16ReadIndex = 0;
                }
            }
        }
        // 缓冲区尾部数据个数小于读取数据个数
        else
        {
            // 计算剩余读取数据及长度
            U16 u16RemainDataLen = u16DataLen - u16BufferTailDataNum;
            U8 *pu8RemainData = (U8 *)(pu8Data + u16BufferTailDataNum);

            // 先把缓冲区尾部数据全部读出来
            memcpy(pu8Data, &(psBuffer->pu8Buffer[psBuffer->u16ReadIndex]), u16BufferTailDataNum);

            // 缓冲区头部数据个数大于或者等于剩余数据个数
            if(u16BufferHeadDataNum >= u16RemainDataLen)
            {
                // 从缓冲区头部读取剩余数据
                memcpy(pu8RemainData, &(psBuffer->pu8Buffer[0]), u16RemainDataLen);
                // 记录读取长度，更新读索引
                u16ReadLen = u16DataLen;
                if(bRemove)
                {
                    psBuffer->u16ReadIndex = u16RemainDataLen;
                }
            }
            // 缓冲区头部数据个数小于剩余数据个数
            else
            {
                // 读取缓冲区头部全部数据
                memcpy(pu8RemainData, &(psBuffer->pu8Buffer[0]), u16BufferHeadDataNum);
                // 记录读取长度，更新读索引
                u16ReadLen = u16BufferTailDataNum + u16BufferHeadDataNum;
                if(bRemove)
                {
                    psBuffer->u16ReadIndex = psBuffer->u16WriteIndex;
                }
            }
        }
    }
    // 缓冲区空
    else
    {
        // 清零读取长度
        u16ReadLen = 0;
    }

    // 更新缓冲区数据个数
    if(bRemove)
    {
        psBuffer->u16DataNum -= u16ReadLen;
    }

    // 返回读取长度
    return u16ReadLen;
}

/*******************************************************************************
  * 函数名：Buffer_Remove
  * 功  能：从缓冲区移除数据
  * 参  数：BufferHandle_tps psBuffer  - 缓冲区句柄
  *         U8 *pu8Data                - 数据
  *         U16 u16DataLen             - 数据长度
  * 返回值：移除个数
  * 说  明：无
*******************************************************************************/
U16 Buffer_Remove(BufferHandle_tps psBuffer, U8 *pu8Data, U16 u16DataLen)
{
    // 移除数据
    return Buffer_Read(psBuffer, pu8Data, u16DataLen, TRUE);
}

/*******************************************************************************
  * 函数名：Buffer_Peek
  * 功  能：从缓冲区查看数据
  * 参  数：BufferHandle_tps psBuffer  - 缓冲区句柄
  *         U8 *pu8Data                - 数据
  *         U16 u16DataLen             - 数据长度
  * 返回值：查看个数
  * 说  明：无
*******************************************************************************/
U16 Buffer_Peek(BufferHandle_tps psBuffer, U8 *pu8Data, U16 u16DataLen)
{
    // 查看数据
    return Buffer_Read(psBuffer, pu8Data, u16DataLen, FALSE);
}

/*******************************************************************************
  * 函数名：Buffer_GetDataNum
  * 功  能：获取缓冲区数据个数
  * 参  数：BufferHandle_tps psBuffer  - 缓冲区句柄
  * 返回值：数据个数
  * 说  明：无
*******************************************************************************/
U16 Buffer_GetDataNum(BufferHandle_tps psBuffer)
{
    // 返回数据个数
    return psBuffer->u16DataNum;
}

/***************************** 文件结束 ***************************************/
